package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.enums.ScoreConditionEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.saas.enums.ScoreOperationTypeEnum;
import com.xbongbong.saas.service.ScoreConditionService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * singleScoreConditionService
 * value属于单值处理
 * 该类主要用于处理，值是字符串，数字单值的字段类型的评分。
 * eg：
 * {
 * text_1:"aa", 单行文本
 * num_1:1.2 ， 数字
 * "text_12":"0dab25fb-c3bc-ed39-0f6c-b41dcaff5cd5", //单选按钮
 * "text_13":"bf86b82c-69cc-321e-a50f-23896959d4aa", //单选框
 * }
 * 等
 */
@Service("singleScoreConditionService")
public class SingleScoreConditionServiceImpl implements ScoreConditionService {
    private static final Logger LOG = LoggerFactory.getLogger(SingleScoreConditionServiceImpl.class);
    //该条条件没有命中，返回 0 分
    private static Double DEFAULT_SCORE_VALUE = 0D;

    /**
     * 所有评分数组接口都能兼容
     *
     * @param dataValue
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double empty(Object dataValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            //时间类型（eg:“跟进时间”为空时，值是0,而不是 完全意义上的空，还是有数据的）
            if (isEmpty(dataValue)) {
                return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 所有评分数组接口都能兼容
     *
     * @param dataValue
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double noempty(Object dataValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (!isEmpty(dataValue)) {
                return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    private Boolean isEmpty(Object dataValue){
        //出现空的场景:(1)数据本身为null (2)数据的值是空串"" （3）如果是特殊的时间数值，比如“最后跟进时间”，表面是空，实际上存的是0
        return Objects.isNull(dataValue) || String.valueOf(dataValue).trim().length() == 0;
    }

    /**
     * @param dataValue              支持单值的数据结构，单行文本，多行文本，数字，日期，，单选按钮，下拉框，最后跟进时间，创建时间 （数组另外处理） eg: text_1:"a", “a” 就是dataValue
     * @param compareValue           compareValue eg: ["a"]
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double equal(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (equal(dataValue, compareValue)) {
                return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * @param dataValue              支持单值的数据结构，单行文本，多行文本，数字，日期，，单选按钮，下拉框，最后跟进时间，创建时间 （数组另外处理）
     * @param compareValue
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double noequal(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (!equal(dataValue, compareValue)) {
                return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 只有数字 和 时间类型会走该判断，统一处理为Long类型，
     *
     * @param dataValue              支持单值的数据结构，数字，日期，最后跟进时间，创建时间
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double greaterequal(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                if(greaterequal(dataValue,compareValue)){
                    return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
                }
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 只有数字 和 时间类型会走该判断，统一处理为Long类型，
     *
     * @param dataValue              支持单值的数据结构，数字，日期，最后跟进时间，创建时间
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double greatethan(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                if (!lessequal(dataValue,compareValue)) {
                    return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
                }
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 只有数字 和 时间类型会走该判断，统一处理为Long类型，
     *
     * @param dataValue              支持单值的数据结构，数字，日期，最后跟进时间，创建时间
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double lessequal(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                if (lessequal(dataValue,compareValue)) {
                    return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
                }
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 只有数字 和 时间类型会走该判断
     *
     * @param dataValue              支持单值的数据结构，数字，日期，最后跟进时间，创建时间
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double lessthan(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                if (!greaterequal(dataValue,compareValue)) {
                    return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
                }
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 只有数字 和 时间类型会走该判断，统一处理为Long类型，
     *
     * @param dataValue              支持单值的数据结构，数字，日期，最后跟进时间，创建时间
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double range(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                if (range(dataValue,compareValue)) {
                    return ScoreOperationTypeEnum.ADD.equals(scoreOperationTypeEnum) ? scoreOperationValue : -scoreOperationValue;
                }
            }
        } catch (Exception e) {
            return DEFAULT_SCORE_VALUE;
        }
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 包含任意一个
     *
     * @param dataValue              数组才有这种操作，下拉复选框，复选框，标签，此类中不做操作
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double include(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        return DEFAULT_SCORE_VALUE;
    }

    /**
     * 同时包含
     *
     * @param dataValue
     * @param scoreOperationValue
     * @param scoreOperationTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public Double allinclude(Object dataValue, List<Object> compareValue, Double scoreOperationValue, ScoreOperationTypeEnum scoreOperationTypeEnum) {
        return DEFAULT_SCORE_VALUE;
    }

    /**
     *等于，不等于 抽取出来
     * @param dataValue
     * @param compareValue
     * @return
     */
    private Boolean equal(Object dataValue, List<Object> compareValue) {
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                Object firstCompareValue = compareValue.get(0);
                String className = dataValue.getClass().getName();
                //数字类型，Integer 和 Double 都先转为Number类型，然后拿到为double比较
                switch (className) {
                    //时间戳存的是long类型 (时间等字段)
                    case LONG:
                        return ((Number) dataValue).longValue() == ((Number) firstCompareValue).longValue();
                    //Integer 和  Oouble 统一取 doubel 值比较 (单选下拉框，code值为数字,金额为 double)
                    case INTEGER:
                    case DOUBLE:
                        return ((Number) dataValue).doubleValue() == ((Number) firstCompareValue).doubleValue();
                    case BIG_DECIMAL:
                        BigDecimal firstCompareBigDecimalValue = null;
                        //这边还要再判断一下  firstCompareValue 的类型,有点难受
                        if(firstCompareValue instanceof BigDecimal){
                            firstCompareBigDecimalValue = (BigDecimal) firstCompareValue;
                        }else if(firstCompareValue instanceof Number){
                            firstCompareBigDecimalValue = new BigDecimal(((Number) firstCompareValue).doubleValue());
                        }
                        return Objects.nonNull(firstCompareBigDecimalValue) && ((((BigDecimal)dataValue).compareTo(firstCompareBigDecimalValue) == 0) );
                    //其余类型就是string,还没想到其他要处理的类型
                    default:
                        return ((String) dataValue).equals((String) firstCompareValue);
                }
            }
        } catch (Exception e) {
            LOG.error("SingleScoreConditionServiceImpl equal 条件判断异常,异常原因-{}-,异常参数 dataValue-{}-,compareValue-{}-", JSON.toJSONString(e.getMessage()), JSON.toJSONString(dataValue), JSON.toJSONString(compareValue));
        }
        return false;
    }

    /**
     * 大于等于 和  小于 抽取出来
     * @param dataValue
     * @param compareValue
     * @return
     */
    private Boolean greaterequal(Object dataValue, List<Object> compareValue){
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                Object firstCompareValue = compareValue.get(0);
                String className = dataValue.getClass().getName();
                //数字类型，Integer 和 Double 都先转为Number类型，然后拿到为double比较
                switch (className) {
                    //时间戳存的是long类型 (时间等字段)
                    case LONG:
                        return ((Number) dataValue).longValue() >= ((Number) firstCompareValue).longValue();
                    //Integer 和  Oouble 统一取 doubel 值比较 (单选下拉框，code值为数字,金额为 double)
                    case INTEGER:
                    case DOUBLE:
                        return ((Number) dataValue).doubleValue() >= ((Number) firstCompareValue).doubleValue();
                    //其余类型就是string,还没想到其他要处理的类型
                    case BIG_DECIMAL:
                        BigDecimal firstCompareBigDecimalValue = null;
                        //这边还要再判断一下  firstCompareValue 的类型,有点难受
                        if(firstCompareValue instanceof BigDecimal){
                            firstCompareBigDecimalValue = (BigDecimal) firstCompareValue;
                        }else if(firstCompareValue instanceof Number){
                            firstCompareBigDecimalValue = new BigDecimal(((Number) firstCompareValue).doubleValue());
                        }
                        return Objects.nonNull(firstCompareBigDecimalValue) && (((BigDecimal)dataValue).compareTo(firstCompareBigDecimalValue) == 1 ) || (((BigDecimal)dataValue).compareTo(firstCompareBigDecimalValue) == 0 );
                    //其余类型就是string,还没想到其他要处理的类型
                    default:
                        return false;
                }
            }
        } catch (Exception e) {
            LOG.error("SingleScoreConditionServiceImpl greaterequal 条件判断异常,异常原因-{}-,异常参数 dataValue-{}-,compareValue-{}-", JSON.toJSONString(e.getMessage()), JSON.toJSONString(dataValue), JSON.toJSONString(compareValue));
        }
        return false;
    }

    /**
     * 小于等于 和  大于 抽取出来
     * @param dataValue
     * @param compareValue
     * @return
     */
    private Boolean lessequal(Object dataValue, List<Object> compareValue){
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                Object firstCompareValue = compareValue.get(0);
                String className = dataValue.getClass().getName();
                //数字类型，Integer 和 Double 都先转为Number类型，然后拿到为double比较
                switch (className) {
                    //时间戳存的是long类型 (时间等字段)
                    case LONG:
                        return ((Number) dataValue).longValue() <= ((Number) firstCompareValue).longValue();
                    //Integer 和  Oouble 统一取 doubel 值比较 (单选下拉框，code值为数字,金额为 double)
                    case INTEGER:
                    case DOUBLE:
                        return ((Number) dataValue).doubleValue() <= ((Number) firstCompareValue).doubleValue();
                    //解释里面的金额字段，解析出来是 “java.math.BigDecimal”
                    case BIG_DECIMAL:
                        BigDecimal firstCompareBigDecimalValue = null;
                        //这边还要再判断一下  firstCompareValue 的类型,有点难受
                        if(firstCompareValue instanceof BigDecimal){
                            firstCompareBigDecimalValue = (BigDecimal) firstCompareValue;
                        }else if(firstCompareValue instanceof Number){
                            firstCompareBigDecimalValue = new BigDecimal(((Number) firstCompareValue).doubleValue());
                        }
                          return Objects.nonNull(firstCompareBigDecimalValue) && (((BigDecimal)dataValue).compareTo(firstCompareBigDecimalValue) == -1 ) || (((BigDecimal)dataValue).compareTo(firstCompareBigDecimalValue) == 0 );
                    //其余类型就是string,还没想到其他要处理的类型
                    default:
                        return false;
                }
            }
        } catch (Exception e) {
            LOG.error("SingleScoreConditionServiceImpl lessequal 条件判断异常,异常原因-{}-,异常参数 dataValue-{}-,compareValue-{}-", JSON.toJSONString(e.getMessage()), JSON.toJSONString(dataValue), JSON.toJSONString(compareValue));
        }
        return false;
    }

    private Boolean range(Object dataValue, List<Object> compareValue ){
        try {
            if (Objects.nonNull(dataValue) && CollectionUtils.isNotEmpty(compareValue)) {
                Object startCompareValue = compareValue.get(0);
                Object endCompareValue = compareValue.get(1);
                String className = dataValue.getClass().getName();
                //数字类型，Integer 和 Double 都先转为Number类型，然后拿到为double比较
                switch (className) {
                    //时间戳存的是long类型 (时间等字段)
                    case LONG:
                        Long dataLongValue = ((Number) dataValue).longValue();
                        Long startLongCompareValue = ((Number) startCompareValue).longValue();
                        Long endLongCompareValue = ((Number) endCompareValue).longValue();
                        return (dataLongValue >= startLongCompareValue && dataLongValue < endLongCompareValue) || (dataLongValue >= endLongCompareValue && dataLongValue < startLongCompareValue);
                    //Integer 和  Oouble 统一取 doubel 值比较 (单选下拉框，code值为数字,金额为 double)
                    case INTEGER:
                    case DOUBLE:
                        double dataDoubleValue = ((Number) dataValue).doubleValue();
                        double startCompareDoubleValue = ((Number) startCompareValue).doubleValue();
                        double endCompareDoubleValue = ((Number) endCompareValue).doubleValue();
                        return (dataDoubleValue >= startCompareDoubleValue && dataDoubleValue < endCompareDoubleValue) || (dataDoubleValue >= endCompareDoubleValue && dataDoubleValue < startCompareDoubleValue);
                    case BIG_DECIMAL:
                        BigDecimal dataDecimalValue = (BigDecimal)dataValue;
                        BigDecimal startCompareBigDecimalValue = null;
                        BigDecimal endCompareBigDecimalValue = null;
                        //这边还要再判断一下  firstCompareValue 的类型,有点难受
                        if(startCompareValue instanceof BigDecimal){
                            startCompareBigDecimalValue = (BigDecimal) startCompareValue;
                            endCompareBigDecimalValue = (BigDecimal) endCompareValue;
                        }else if(startCompareValue instanceof Number){
                            startCompareBigDecimalValue = new BigDecimal(((Number) startCompareValue).doubleValue());
                            endCompareBigDecimalValue = new BigDecimal(((Number) endCompareValue).doubleValue());
                        }
                        //data和开始值的比较结果
                        int startValueCompareResult = dataDecimalValue.compareTo(startCompareBigDecimalValue);
                        //data和结束值的比较结果
                        int endValueCompareResult = dataDecimalValue.compareTo(endCompareBigDecimalValue);
                        return Objects.nonNull(startCompareBigDecimalValue) && Objects.nonNull(endCompareBigDecimalValue) && (
                                //大于开始值小于结束值 或者 大于结束值小于开始值  （-1，0,1 对应 小于，等于，大于） （eg: 3~5 就是 >= 3 并<5 ,或者 >=5 并 <3,左边包含右不包含 )
                                ((startValueCompareResult >= 0) && (endValueCompareResult == -1)) || ((startValueCompareResult <= 0) && (endValueCompareResult == 1))
                                );
                    //其余类型就是string,还没想到其他要处理的类型
                    default:
                        return false;
                }
            }
        }catch (Exception e){
            LOG.error("SingleScoreConditionServiceImpl range 条件判断异常,异常原因-{}-,异常参数 dataValue-{}-,compareValue-{}-", JSON.toJSONString(e.getMessage()), JSON.toJSONString(dataValue), JSON.toJSONString(compareValue));
        }
        return false;
    }

}
